#ifndef __MY_DATA__
#define __MY_DATA__
#include "util.hpp"
#include <mutex>
#include <cstdlib>
#include <mysql/mysql.h>

namespace aod{
#define HOST "127.0.0.1"
#define USER "root"
#define PASS "15115655971Lml"
#define NAME "aod_system"
    static MYSQL* MysqlInit()
    {
        MYSQL* mysql = mysql_init(NULL);//句柄初始化
        mysql_set_character_set(mysql,"utf8");//设置字符编码
        if(mysql==NULL){
            std::cerr<<"init mysql instance failed!"<<std::endl;
            return NULL;
        }
        if(mysql_real_connect(mysql,HOST,USER,PASS,NAME,0/*0就是默认3306*/,NULL,0)==nullptr){//连接mysql
            std::cerr<<"connect mysql server failed!"<<std::endl;
            mysql_close(mysql);
            return NULL;
        }
        return mysql;
    } 
    static void MysqlDestroy(MYSQL* mysql)
    {
        if(mysql!=NULL)
        {
            mysql_close(mysql);
        }
    }
    static bool MysqlQuery(MYSQL* mysql,const std::string &sql)
    {
        int ret = mysql_query(mysql,sql.c_str());//查询即执行sql !!!
        if(ret!=0){
            std::cerr<< sql <<std::endl;
            std::cerr<< mysql_error(mysql) <<std::endl;
            return false;
        }
        return true;
    }

    class TableVideo{
        private:
            MYSQL* _mysql;//一个对象就是一个客户端，管理一张表
            std::mutex _mutex;//防备操作对象在多线程中使用存在的线程安全 问题
        public:
            TableVideo()//完成mysql句柄初始化
            {
                _mysql = MysqlInit();
                if(_mysql == NULL){
                    exit(-1);
                }
            }
            ~TableVideo()//释放msyql操作句柄
            {
                MysqlDestroy(_mysql);
            }
            bool Insert(const Json::Value &video)//新增-传入视频信息
            {
                //id name info video image
                std::string sql;
                sql.resize(4094 + video["info"].asString().size());//防止简介过长
                #define INSERT_VIDEO "insert tb_video values(null,'%s','%s','%s','%s');"
                //要完成还需要鸽子1校验，不然直接使用可能会出问题
                sprintf(&sql[0],INSERT_VIDEO,video["name"].asCString(),
                                             video["info"].asCString(),
                                             video["video"].asCString(),
                                             video["image"].asCString());
                return MysqlQuery(_mysql,sql);
            }
            bool Update(int video_id,const Json::Value &video) //修改-传入视频id，和信息
            {
                //id name info video image
                std::string sql;
                sql.resize(4094 + video["info"].asString().size());//防止简介过长
                #define UPDATE_VIDEO "update tb_video set name='%s',info='%s' where id=%d;"
                sprintf(&sql[0],UPDATE_VIDEO,video["name"].asCString(),
                                             video["info"].asCString(),
                                             video_id);
                return MysqlQuery(_mysql,sql);
            }
            bool Delete(const int video_id)//删除-传入视频ID
            {
                #define DELETE_VIDEO "delete from tb_video where id=%d;"
                char sql[1024] = {0};
                sprintf(sql,DELETE_VIDEO,video_id);
                return MysqlQuery(_mysql,sql);
            }
            bool SelectAll(Json::Value *videos)//查询所有--输出所有视频信息
            {
                #define SELECTEALL_VIDEO "select * from tb_video;"
                _mutex.lock();//-----lock  start 查询到的结果与保存数据到本地应该要是原子的
                bool ret = MysqlQuery(_mysql,SELECTEALL_VIDEO);
                if(ret == false){
                    _mutex.unlock();
                    return false;
                }
                MYSQL_RES *res = mysql_store_result(_mysql);//保存结果集
                if(res == NULL){
                    std::cerr<<"mysql store result failed!"<<std::endl;
                    _mutex.unlock();
                    return false;
                }
                _mutex.unlock();//-----lock  end
                int num_rows = mysql_num_rows(res);//获取结果集的行数
                for(int i=0;i<num_rows;i++){
                    MYSQL_ROW row = mysql_fetch_row(res);//获取每一行的结果,内部会自动++
                    Json::Value video;
                    video["id"] = atoi(row[0]);
                    video["name"] = row[1];
                    video["info"] = row[2];
                    video["vedio"] = row[3];
                    video["image"] = row[4];

                    videos->append(video);
                }
                mysql_free_result(res);//释放结果集
                return true;
            }
            bool SelectOne(int video_id,Json::Value *video)//查询单个-输入视频id,输出信息
            {
                #define SELECTEONE_VIDEO "select * from tb_video where id='%d'"
                char sql[1024]={0};
                sprintf(sql,SELECTEONE_VIDEO,video_id);
                _mutex.lock();//-----lock  start 查询到的结果与保存数据到本地应该要是原子的
                bool ret = MysqlQuery(_mysql,sql);
                if(ret == false){
                    _mutex.unlock();
                    return false;
                }
                MYSQL_RES *res = mysql_store_result(_mysql);//保存结果集 
                if(res == NULL){
                    std::cerr<<"mysql store result failed!"<<std::endl;
                    mysql_free_result(res);//注意退出前要释放结果集
                    _mutex.unlock();
                    return false;
                }
                _mutex.unlock();//-----lock  end
                int num_rows = mysql_num_rows(res);//获取结果集的行数
                if(num_rows!=1){
                    std::cerr<<"have no data!"<<std::endl;
                    mysql_free_result(res);
                    return false;
                }
                MYSQL_ROW row = mysql_fetch_row(res);//获取每一行的结果,内部会自动++
                (*video)["id"] = atoi(row[0]);
                (*video)["name"] = row[1];
                (*video)["info"] = row[2];
                (*video)["vedio"] = row[3];
                (*video)["image"] = row[4];

                mysql_free_result(res);//释放结果集
                return true;
            }
            bool SelectLike(const std::string &key,Json::Value *videos)//模糊匹配-输入名称关键字，输出视频信息
            {
                #define SELECTELIKE_VIDEO "select * from tb_video where name like '%%%s%%';"
                char sql[1024]={0};
                sprintf(sql,SELECTELIKE_VIDEO,key.c_str());
                _mutex.lock();//-----lock  start 查询到的结果与保存数据到本地应该要是原子的
                bool ret = MysqlQuery(_mysql,sql);
                if(ret == false){
                    _mutex.unlock();
                    return false;
                }
                MYSQL_RES *res = mysql_store_result(_mysql);//保存结果集
                if(res == NULL){
                    std::cerr<<"mysql store result failed!"<<std::endl;
                    _mutex.unlock();
                    return false;
                }
                _mutex.unlock();//-----lock  end
                int num_rows = mysql_num_rows(res);//获取结果集的行数
                for(int i=0;i<num_rows;i++){
                    MYSQL_ROW row = mysql_fetch_row(res);//获取每一行的结果,内部会自动++
                    Json::Value video;
                    video["id"] = atoi(row[0]);
                    video["name"] = row[1];
                    video["info"] = row[2];
                    video["vedio"] = row[3];
                    video["image"] = row[4];

                    videos->append(video);
                }
                mysql_free_result(res);//释放结果集
                return true;
            }
    };
};

#endif